#!/usr/bin/env python3
"""
Claude Code <-> Copilot 请求转换器
实现两种API格式之间的双向转换
"""

import json
import re
import uuid
from typing import Dict, List, Any, Optional, Union
from pathlib import Path


class RequestTransformer:
    def __init__(self, mapping_file: str = "field_mapping.json"):
        """初始化转换器"""
        self.mapping_file = Path(mapping_file)
        self.mapping = self._load_mapping()
        
    def _load_mapping(self) -> Dict[str, Any]:
        """加载映射配置"""
        with open(self.mapping_file, 'r', encoding='utf-8') as f:
            return json.load(f)
    
    def claude_to_copilot(self, claude_request: Dict[str, Any]) -> Dict[str, Any]:
        """将Claude Code请求转换为Copilot格式"""
        
        # 转换URL
        copilot_request = {
            'method': 'POST',
            'url': self.mapping['url_mapping']['claude_to_copilot']['base_url'] +
                   self.mapping['url_mapping']['claude_to_copilot']['endpoint'],
            'headers': self._transform_headers_claude_to_copilot(claude_request.get('headers', {})),
            'body': self._transform_body_claude_to_copilot(claude_request.get('body', {}))
        }
        
        return copilot_request
    
    def copilot_to_claude(self, copilot_request: Dict[str, Any]) -> Dict[str, Any]:
        """将Copilot请求转换为Claude Code格式"""
        
        claude_request = {
            'method': 'POST',
            'url': '/v1/messages?beta=true',
            'headers': self._transform_headers_copilot_to_claude(copilot_request.get('headers', {})),
            'body': self._transform_body_copilot_to_claude(copilot_request.get('body', {}))
        }
        
        return claude_request
    
    def _transform_headers_claude_to_copilot(self, claude_headers: Dict[str, str]) -> Dict[str, str]:
        """转换请求头：Claude -> Copilot"""
        copilot_headers = {}
        
        # 添加必需的Copilot头部
        required_headers = self.mapping['header_mapping']['claude_to_copilot']['required_headers']
        for key, value in required_headers.items():
            if '{copilot_token}' in str(value):
                # 需要替换为实际的Copilot token
                auth_header = claude_headers.get('Authorization', '')
                copilot_token = self._convert_token_claude_to_copilot(auth_header)
                copilot_headers[key] = value.replace('{copilot_token}', copilot_token)
            else:
                copilot_headers[key] = value
        
        # 转换特定头部
        transforms = self.mapping['header_mapping']['claude_to_copilot']['header_transforms']
        for claude_key, copilot_key in transforms.items():
            if claude_key in claude_headers and copilot_key:
                copilot_headers[copilot_key] = claude_headers[claude_key]
        
        # 添加动态头部
        copilot_headers.update({
            'x-interaction-id': str(uuid.uuid4()),
            'x-request-id': str(uuid.uuid4()),
            'vscode-machineid': self._generate_machine_id(),
            'vscode-sessionid': self._generate_session_id()
        })
        
        return copilot_headers
    
    def _transform_headers_copilot_to_claude(self, copilot_headers: Dict[str, str]) -> Dict[str, str]:
        """转换请求头：Copilot -> Claude"""
        claude_headers = {
            'host': 'api.anthropic.com',
            'connection': 'keep-alive',
            'Accept': 'application/json',
            'content-type': 'application/json',
            'User-Agent': 'claude-cli/1.0.68 (external, cli)',
            'anthropic-version': '2023-06-01',
            'x-app': 'cli',
            'accept-language': '*',
            'sec-fetch-mode': 'cors',
            'accept-encoding': 'br, gzip, deflate'
        }
        
        # 转换认证信息
        auth_header = copilot_headers.get('authorization', '')
        if auth_header:
            claude_token = self._convert_token_copilot_to_claude(auth_header)
            claude_headers['Authorization'] = f'Bearer {claude_token}'
        
        return claude_headers
    
    def _transform_body_claude_to_copilot(self, claude_body: Union[str, Dict[str, Any]]) -> Dict[str, Any]:
        """转换请求体：Claude -> Copilot"""
        if isinstance(claude_body, str):
            try:
                claude_body = json.loads(claude_body)
            except:
                return {}
        
        copilot_body = {
            'messages': self._transform_messages_claude_to_copilot(claude_body.get('messages', [])),
            'model': self._map_model_claude_to_copilot(claude_body.get('model', 'claude-sonnet-4-20250514')),
            'temperature': claude_body.get('temperature', 0),
            'top_p': claude_body.get('top_p', 1),
            'n': 1,
            'max_tokens': claude_body.get('max_tokens', 16000),
            'stream': True
        }
        
        # 转换工具定义
        if 'tools' in claude_body:
            copilot_body['tools'] = self._transform_tools_claude_to_copilot(claude_body['tools'])
            copilot_body['tool_choice'] = 'auto'
        
        # 处理系统消息
        if 'system' in claude_body:
            copilot_body['messages'] = self._merge_system_messages(
                claude_body['system'], copilot_body['messages']
            )
        
        return copilot_body
    
    def _transform_body_copilot_to_claude(self, copilot_body: Union[str, Dict[str, Any]]) -> Dict[str, Any]:
        """转换请求体：Copilot -> Claude"""
        if isinstance(copilot_body, str):
            try:
                copilot_body = json.loads(copilot_body)
            except:
                return {}
        
        claude_body = {
            'model': self._map_model_copilot_to_claude(copilot_body.get('model', 'claude-sonnet-4')),
            'messages': self._transform_messages_copilot_to_claude(copilot_body.get('messages', [])),
            'temperature': copilot_body.get('temperature', 1),
            'max_tokens': copilot_body.get('max_tokens', 21333)
        }
        
        # 转换工具定义
        if 'tools' in copilot_body:
            claude_body['tools'] = self._transform_tools_copilot_to_claude(copilot_body['tools'])
        
        # 提取系统消息
        system_messages = self._extract_system_messages(copilot_body.get('messages', []))
        if system_messages:
            claude_body['system'] = system_messages
        
        return claude_body
    
    def _transform_tools_claude_to_copilot(self, claude_tools: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
        """转换工具定义：Claude -> Copilot"""
        copilot_tools = []
        tool_mapping = self.mapping['tool_mapping']['claude_to_copilot']
        
        for tool in claude_tools:
            tool_name = tool.get('name')
            if tool_name in tool_mapping:
                mapping = tool_mapping[tool_name]
                
                if mapping.get('action') == 'remove':
                    continue  # 跳过不支持的工具
                
                target_name = mapping.get('target')
                if target_name:
                    copilot_tool = {
                        'type': 'function',
                        'function': {
                            'name': target_name,
                            'description': tool.get('description', ''),
                            'parameters': self._transform_tool_parameters(
                                tool.get('input_schema', {}), 
                                mapping.get('parameter_mapping', {})
                            )
                        }
                    }
                    copilot_tools.append(copilot_tool)
        
        return copilot_tools
    
    def _transform_tools_copilot_to_claude(self, copilot_tools: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
        """转换工具定义：Copilot -> Claude"""
        claude_tools = []
        tool_mapping = self.mapping['tool_mapping']['copilot_to_claude']
        
        for tool in copilot_tools:
            if tool.get('type') == 'function':
                func = tool.get('function', {})
                func_name = func.get('name')
                
                if func_name in tool_mapping:
                    mapping = tool_mapping[func_name]
                    target_name = mapping.get('target')
                    
                    claude_tool = {
                        'name': target_name,
                        'description': func.get('description', ''),
                        'input_schema': self._transform_tool_parameters_reverse(
                            func.get('parameters', {}),
                            mapping.get('parameter_mapping', {})
                        )
                    }
                    claude_tools.append(claude_tool)
        
        return claude_tools
    
    def _transform_messages_claude_to_copilot(self, claude_messages: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
        """转换消息格式：Claude -> Copilot"""
        copilot_messages = []
        
        for message in claude_messages:
            copilot_msg = {
                'role': message.get('role', 'user'),
                'content': self._extract_text_content(message.get('content', []))
            }
            
            # 处理工具调用
            if 'tool_calls' in message:
                copilot_msg['tool_calls'] = self._transform_tool_calls_claude_to_copilot(
                    message['tool_calls']
                )
            
            copilot_messages.append(copilot_msg)
        
        return copilot_messages
    
    def _transform_messages_copilot_to_claude(self, copilot_messages: List[Dict[str, Any]]) -> List[Dict[str, Any]]:
        """转换消息格式：Copilot -> Claude"""
        claude_messages = []
        
        for message in copilot_messages:
            claude_msg = {
                'role': message.get('role', 'user'),
                'content': []
            }
            
            # 处理文本内容
            content = message.get('content', '')
            if content:
                claude_msg['content'].append({
                    'type': 'text',
                    'text': content
                })
            
            # 处理工具调用
            if 'tool_calls' in message:
                claude_msg['tool_use'] = self._transform_tool_calls_copilot_to_claude(
                    message['tool_calls']
                )
            
            claude_messages.append(claude_msg)
        
        return claude_messages
    
    def _map_model_claude_to_copilot(self, claude_model: str) -> str:
        """映射模型名称：Claude -> Copilot"""
        model_mapping = self.mapping['body_mapping']['claude_to_copilot']['model_mapping']
        return model_mapping.get(claude_model, 'claude-sonnet-4')
    
    def _map_model_copilot_to_claude(self, copilot_model: str) -> str:
        """映射模型名称：Copilot -> Claude"""
        model_mapping = self.mapping['body_mapping']['claude_to_copilot']['model_mapping']
        # 反向映射
        reverse_mapping = {v: k for k, v in model_mapping.items()}
        return reverse_mapping.get(copilot_model, 'claude-sonnet-4-20250514')
    
    def _convert_token_claude_to_copilot(self, claude_auth: str) -> str:
        """转换认证令牌：Claude -> Copilot"""
        # 从Claude token生成Copilot token格式
        # 这里需要实际的令牌转换逻辑
        token = claude_auth.replace('Bearer ', '')
        return f"tid=994ad95b10a5f9efa6efb591484e1ff0;exp=1754407862;sku=copilot_standalone_seat_quota;proxy-ep=proxy.business.githubcopilot.com"
    
    def _convert_token_copilot_to_claude(self, copilot_auth: str) -> str:
        """转换认证令牌：Copilot -> Claude"""
        # 从Copilot token生成Claude token格式  
        return "sk-RU0JWcPqgtwFp8iTwMILZxMrvIOwmxKmOBLd9t7LOlmF9hOy"
    
    def _generate_machine_id(self) -> str:
        """生成机器ID"""
        return "94d35625a61fd8f9fa14b64f9bf5c1cafe88359acc2dfa71fc527c04ec688653"
    
    def _generate_session_id(self) -> str:
        """生成会话ID"""
        return f"3a7e58f3-be05-4af4-a4e2-8356f90c896f{int(__import__('time').time())}"
    
    def _extract_text_content(self, content: Union[str, List[Dict]]) -> str:
        """提取文本内容"""
        if isinstance(content, str):
            return content
        
        text_parts = []
        for item in content:
            if isinstance(item, dict) and item.get('type') == 'text':
                text_parts.append(item.get('text', ''))
        
        return '\n'.join(text_parts)
    
    def _merge_system_messages(self, system_msgs: List[Dict], user_msgs: List[Dict]) -> List[Dict]:
        """合并系统消息到用户消息中"""
        merged = []
        
        # 添加系统消息
        for sys_msg in system_msgs:
            merged.append({
                'role': 'system',
                'content': sys_msg.get('text', '')
            })
        
        # 添加用户消息
        merged.extend(user_msgs)
        
        return merged
    
    def _extract_system_messages(self, messages: List[Dict]) -> List[Dict]:
        """从消息中提取系统消息"""
        system_msgs = []
        
        for msg in messages:
            if msg.get('role') == 'system':
                system_msgs.append({
                    'type': 'text',
                    'text': msg.get('content', '')
                })
        
        return system_msgs
    
    def _transform_tool_parameters(self, input_schema: Dict, param_mapping: Dict) -> Dict:
        """转换工具参数架构"""
        # 简化处理，实际实现需要更复杂的架构转换
        return input_schema
    
    def _transform_tool_parameters_reverse(self, parameters: Dict, param_mapping: Dict) -> Dict:
        """反向转换工具参数架构"""
        return parameters
    
    def _transform_tool_calls_claude_to_copilot(self, tool_calls: List[Dict]) -> List[Dict]:
        """转换工具调用：Claude -> Copilot"""
        # 实现工具调用转换逻辑
        return tool_calls
    
    def _transform_tool_calls_copilot_to_claude(self, tool_calls: List[Dict]) -> List[Dict]:
        """转换工具调用：Copilot -> Claude"""
        return tool_calls